home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / tarfile.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-13  |  46.9 KB  |  1,899 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __version__ = '$Revision: 60730 $'
  5. version = '0.8.0'
  6. __author__ = 'Lars Gust\xe4bel (lars@gustaebel.de)'
  7. __date__ = '$Date: 2008-02-11 13:36:07 -0500 (Mon, 11 Feb 2008) $'
  8. __cvsid__ = '$Id: tarfile.py 60730 2008-02-11 18:36:07Z lars.gustaebel $'
  9. __credits__ = 'Gustavo Niemeyer, Niels Gust\xe4bel, Richard Townsend.'
  10. import sys
  11. import os
  12. import shutil
  13. import stat
  14. import errno
  15. import time
  16. import struct
  17. import copy
  18. if sys.platform == 'mac':
  19.     raise ImportError, 'tarfile does not work for platform==mac'
  20.  
  21.  
  22. try:
  23.     import grp
  24.     import pwd
  25. except ImportError:
  26.     grp = pwd = None
  27.  
  28. __all__ = [
  29.     'TarFile',
  30.     'TarInfo',
  31.     'is_tarfile',
  32.     'TarError']
  33. NUL = '\x00'
  34. BLOCKSIZE = 512
  35. RECORDSIZE = BLOCKSIZE * 20
  36. MAGIC = 'ustar'
  37. VERSION = '00'
  38. LENGTH_NAME = 100
  39. LENGTH_LINK = 100
  40. LENGTH_PREFIX = 155
  41. MAXSIZE_MEMBER = 0x1FFFFFFFFL
  42. REGTYPE = '0'
  43. AREGTYPE = '\x00'
  44. LNKTYPE = '1'
  45. SYMTYPE = '2'
  46. CHRTYPE = '3'
  47. BLKTYPE = '4'
  48. DIRTYPE = '5'
  49. FIFOTYPE = '6'
  50. CONTTYPE = '7'
  51. GNUTYPE_LONGNAME = 'L'
  52. GNUTYPE_LONGLINK = 'K'
  53. GNUTYPE_SPARSE = 'S'
  54. SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, GNUTYPE_SPARSE)
  55. REGULAR_TYPES = (REGTYPE, AREGTYPE, CONTTYPE, GNUTYPE_SPARSE)
  56. S_IFLNK = 40960
  57. S_IFREG = 32768
  58. S_IFBLK = 24576
  59. S_IFDIR = 16384
  60. S_IFCHR = 8192
  61. S_IFIFO = 4096
  62. TSUID = 2048
  63. TSGID = 1024
  64. TSVTX = 512
  65. TUREAD = 256
  66. TUWRITE = 128
  67. TUEXEC = 64
  68. TGREAD = 32
  69. TGWRITE = 16
  70. TGEXEC = 8
  71. TOREAD = 4
  72. TOWRITE = 2
  73. TOEXEC = 1
  74.  
  75. def stn(s, length):
  76.     return s[:length] + (length - len(s)) * NUL
  77.  
  78.  
  79. def nts(s):
  80.     p = s.find('\x00')
  81.     if p == -1:
  82.         return s
  83.     
  84.     return s[:p]
  85.  
  86.  
  87. def nti(s):
  88.     if s[0] != chr(128):
  89.         if not nts(s):
  90.             pass
  91.         n = int('0', 8)
  92.     else:
  93.         n = 0x0L
  94.         for i in xrange(len(s) - 1):
  95.             n <<= 8
  96.             n += ord(s[i + 1])
  97.         
  98.     return n
  99.  
  100.  
  101. def itn(n, digits = 8, posix = False):
  102.     if n <= n:
  103.         pass
  104.     elif n < 8 ** (digits - 1):
  105.         s = '%0*o' % (digits - 1, n) + NUL
  106.     elif posix:
  107.         raise ValueError('overflow in number field')
  108.     
  109.     if n < 0:
  110.         n = struct.unpack('L', struct.pack('l', n))[0]
  111.     
  112.     s = ''
  113.     for i in xrange(digits - 1):
  114.         s = chr(n & 255) + s
  115.         n >>= 8
  116.     
  117.     s = chr(128) + s
  118.     return s
  119.  
  120.  
  121. def calc_chksums(buf):
  122.     unsigned_chksum = 256 + sum(struct.unpack('148B', buf[:148]) + struct.unpack('356B', buf[156:512]))
  123.     signed_chksum = 256 + sum(struct.unpack('148b', buf[:148]) + struct.unpack('356b', buf[156:512]))
  124.     return (unsigned_chksum, signed_chksum)
  125.  
  126.  
  127. def copyfileobj(src, dst, length = None):
  128.     if length == 0:
  129.         return None
  130.     
  131.     if length is None:
  132.         shutil.copyfileobj(src, dst)
  133.         return None
  134.     
  135.     BUFSIZE = 16384
  136.     (blocks, remainder) = divmod(length, BUFSIZE)
  137.     for b in xrange(blocks):
  138.         buf = src.read(BUFSIZE)
  139.         if len(buf) < BUFSIZE:
  140.             raise IOError('end of file reached')
  141.         
  142.         dst.write(buf)
  143.     
  144.     if remainder != 0:
  145.         buf = src.read(remainder)
  146.         if len(buf) < remainder:
  147.             raise IOError('end of file reached')
  148.         
  149.         dst.write(buf)
  150.     
  151.  
  152. filemode_table = (((S_IFLNK, 'l'), (S_IFREG, '-'), (S_IFBLK, 'b'), (S_IFDIR, 'd'), (S_IFCHR, 'c'), (S_IFIFO, 'p')), ((TUREAD, 'r'),), ((TUWRITE, 'w'),), ((TUEXEC | TSUID, 's'), (TSUID, 'S'), (TUEXEC, 'x')), ((TGREAD, 'r'),), ((TGWRITE, 'w'),), ((TGEXEC | TSGID, 's'), (TSGID, 'S'), (TGEXEC, 'x')), ((TOREAD, 'r'),), ((TOWRITE, 'w'),), ((TOEXEC | TSVTX, 't'), (TSVTX, 'T'), (TOEXEC, 'x')))
  153.  
  154. def filemode(mode):
  155.     perm = []
  156.     for table in filemode_table:
  157.         for bit, char in table:
  158.             if mode & bit == bit:
  159.                 perm.append(char)
  160.                 break
  161.                 continue
  162.         
  163.     
  164.     return ''.join(perm)
  165.  
  166. if os.sep != '/':
  167.     
  168.     normpath = lambda path: os.path.normpath(path).replace(os.sep, '/')
  169. else:
  170.     normpath = os.path.normpath
  171.  
  172. class TarError(Exception):
  173.     pass
  174.  
  175.  
  176. class ExtractError(TarError):
  177.     pass
  178.  
  179.  
  180. class ReadError(TarError):
  181.     pass
  182.  
  183.  
  184. class CompressionError(TarError):
  185.     pass
  186.  
  187.  
  188. class StreamError(TarError):
  189.     pass
  190.  
  191.  
  192. class _LowLevelFile:
  193.     
  194.     def __init__(self, name, mode):
  195.         mode = {
  196.             'r': os.O_RDONLY,
  197.             'w': os.O_WRONLY | os.O_CREAT | os.O_TRUNC }[mode]
  198.         if hasattr(os, 'O_BINARY'):
  199.             mode |= os.O_BINARY
  200.         
  201.         self.fd = os.open(name, mode)
  202.  
  203.     
  204.     def close(self):
  205.         os.close(self.fd)
  206.  
  207.     
  208.     def read(self, size):
  209.         return os.read(self.fd, size)
  210.  
  211.     
  212.     def write(self, s):
  213.         os.write(self.fd, s)
  214.  
  215.  
  216.  
  217. class _Stream:
  218.     
  219.     def __init__(self, name, mode, comptype, fileobj, bufsize):
  220.         self._extfileobj = True
  221.         if fileobj is None:
  222.             fileobj = _LowLevelFile(name, mode)
  223.             self._extfileobj = False
  224.         
  225.         if comptype == '*':
  226.             fileobj = _StreamProxy(fileobj)
  227.             comptype = fileobj.getcomptype()
  228.         
  229.         if not name:
  230.             pass
  231.         self.name = ''
  232.         self.mode = mode
  233.         self.comptype = comptype
  234.         self.fileobj = fileobj
  235.         self.bufsize = bufsize
  236.         self.buf = ''
  237.         self.pos = 0x0L
  238.         self.closed = False
  239.         if comptype == 'gz':
  240.             
  241.             try:
  242.                 import zlib
  243.             except ImportError:
  244.                 raise CompressionError('zlib module is not available')
  245.  
  246.             self.zlib = zlib
  247.             self.crc = zlib.crc32('')
  248.             if mode == 'r':
  249.                 self._init_read_gz()
  250.             else:
  251.                 self._init_write_gz()
  252.         
  253.         if comptype == 'bz2':
  254.             
  255.             try:
  256.                 import bz2
  257.             except ImportError:
  258.                 raise CompressionError('bz2 module is not available')
  259.  
  260.             if mode == 'r':
  261.                 self.dbuf = ''
  262.                 self.cmp = bz2.BZ2Decompressor()
  263.             else:
  264.                 self.cmp = bz2.BZ2Compressor()
  265.         
  266.  
  267.     
  268.     def __del__(self):
  269.         if hasattr(self, 'closed') and not (self.closed):
  270.             self.close()
  271.         
  272.  
  273.     
  274.     def _init_write_gz(self):
  275.         self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, -(self.zlib.MAX_WBITS), self.zlib.DEF_MEM_LEVEL, 0)
  276.         timestamp = struct.pack('<L', long(time.time()))
  277.         self._Stream__write('\x1f\x8b\x08\x08%s\x02\xff' % timestamp)
  278.         if self.name.endswith('.gz'):
  279.             self.name = self.name[:-3]
  280.         
  281.         self._Stream__write(self.name + NUL)
  282.  
  283.     
  284.     def write(self, s):
  285.         if self.comptype == 'gz':
  286.             self.crc = self.zlib.crc32(s, self.crc)
  287.         
  288.         self.pos += len(s)
  289.         if self.comptype != 'tar':
  290.             s = self.cmp.compress(s)
  291.         
  292.         self._Stream__write(s)
  293.  
  294.     
  295.     def _Stream__write(self, s):
  296.         self.buf += s
  297.         while len(self.buf) > self.bufsize:
  298.             self.fileobj.write(self.buf[:self.bufsize])
  299.             self.buf = self.buf[self.bufsize:]
  300.             continue
  301.             self
  302.  
  303.     
  304.     def close(self):
  305.         if self.closed:
  306.             return None
  307.         
  308.         if self.mode == 'w' and self.comptype != 'tar':
  309.             self.buf += self.cmp.flush()
  310.         
  311.         if self.mode == 'w' and self.buf:
  312.             self.fileobj.write(self.buf)
  313.             self.buf = ''
  314.             if self.comptype == 'gz':
  315.                 self.fileobj.write(struct.pack('<L', self.crc & 0xFFFFFFFFL))
  316.                 self.fileobj.write(struct.pack('<L', self.pos & 0xFFFFFFFFL))
  317.             
  318.         
  319.         if not self._extfileobj:
  320.             self.fileobj.close()
  321.         
  322.         self.closed = True
  323.  
  324.     
  325.     def _init_read_gz(self):
  326.         self.cmp = self.zlib.decompressobj(-(self.zlib.MAX_WBITS))
  327.         self.dbuf = ''
  328.         if self._Stream__read(2) != '\x1f\x8b':
  329.             raise ReadError('not a gzip file')
  330.         
  331.         if self._Stream__read(1) != '\x08':
  332.             raise CompressionError('unsupported compression method')
  333.         
  334.         flag = ord(self._Stream__read(1))
  335.         self._Stream__read(6)
  336.         if flag & 4:
  337.             xlen = ord(self._Stream__read(1)) + 256 * ord(self._Stream__read(1))
  338.             self.read(xlen)
  339.         
  340.         if flag & 8:
  341.             while True:
  342.                 s = self._Stream__read(1)
  343.                 if not s or s == NUL:
  344.                     break
  345.                     continue
  346.         
  347.         if flag & 16:
  348.             while True:
  349.                 s = self._Stream__read(1)
  350.                 if not s or s == NUL:
  351.                     break
  352.                     continue
  353.         
  354.         if flag & 2:
  355.             self._Stream__read(2)
  356.         
  357.  
  358.     
  359.     def tell(self):
  360.         return self.pos
  361.  
  362.     
  363.     def seek(self, pos = 0):
  364.         if pos - self.pos >= 0:
  365.             (blocks, remainder) = divmod(pos - self.pos, self.bufsize)
  366.             for i in xrange(blocks):
  367.                 self.read(self.bufsize)
  368.             
  369.             self.read(remainder)
  370.         else:
  371.             raise StreamError('seeking backwards is not allowed')
  372.         return self.pos
  373.  
  374.     
  375.     def read(self, size = None):
  376.         if size is None:
  377.             t = []
  378.             while True:
  379.                 buf = self._read(self.bufsize)
  380.                 if not buf:
  381.                     break
  382.                 
  383.                 t.append(buf)
  384.             buf = ''.join(t)
  385.         else:
  386.             buf = self._read(size)
  387.         self.pos += len(buf)
  388.         return buf
  389.  
  390.     
  391.     def _read(self, size):
  392.         if self.comptype == 'tar':
  393.             return self._Stream__read(size)
  394.         
  395.         c = len(self.dbuf)
  396.         t = [
  397.             self.dbuf]
  398.         while c < size:
  399.             buf = self._Stream__read(self.bufsize)
  400.             if not buf:
  401.                 break
  402.             
  403.             buf = self.cmp.decompress(buf)
  404.             t.append(buf)
  405.             c += len(buf)
  406.         t = ''.join(t)
  407.         self.dbuf = t[size:]
  408.         return t[:size]
  409.  
  410.     
  411.     def _Stream__read(self, size):
  412.         c = len(self.buf)
  413.         t = [
  414.             self.buf]
  415.         while c < size:
  416.             buf = self.fileobj.read(self.bufsize)
  417.             if not buf:
  418.                 break
  419.             
  420.             t.append(buf)
  421.             c += len(buf)
  422.         t = ''.join(t)
  423.         self.buf = t[size:]
  424.         return t[:size]
  425.  
  426.  
  427.  
  428. class _StreamProxy(object):
  429.     
  430.     def __init__(self, fileobj):
  431.         self.fileobj = fileobj
  432.         self.buf = self.fileobj.read(BLOCKSIZE)
  433.  
  434.     
  435.     def read(self, size):
  436.         self.read = self.fileobj.read
  437.         return self.buf
  438.  
  439.     
  440.     def getcomptype(self):
  441.         if self.buf.startswith('\x1f\x8b\x08'):
  442.             return 'gz'
  443.         
  444.         if self.buf.startswith('BZh91'):
  445.             return 'bz2'
  446.         
  447.         return 'tar'
  448.  
  449.     
  450.     def close(self):
  451.         self.fileobj.close()
  452.  
  453.  
  454.  
  455. class _BZ2Proxy(object):
  456.     blocksize = 16384
  457.     
  458.     def __init__(self, fileobj, mode):
  459.         self.fileobj = fileobj
  460.         self.mode = mode
  461.         self.init()
  462.  
  463.     
  464.     def init(self):
  465.         import bz2
  466.         self.pos = 0
  467.         if self.mode == 'r':
  468.             self.bz2obj = bz2.BZ2Decompressor()
  469.             self.fileobj.seek(0)
  470.             self.buf = ''
  471.         else:
  472.             self.bz2obj = bz2.BZ2Compressor()
  473.  
  474.     
  475.     def read(self, size):
  476.         b = [
  477.             self.buf]
  478.         x = len(self.buf)
  479.         while x < size:
  480.             
  481.             try:
  482.                 raw = self.fileobj.read(self.blocksize)
  483.                 data = self.bz2obj.decompress(raw)
  484.                 b.append(data)
  485.             except EOFError:
  486.                 break
  487.  
  488.             x += len(data)
  489.         self.buf = ''.join(b)
  490.         buf = self.buf[:size]
  491.         self.buf = self.buf[size:]
  492.         self.pos += len(buf)
  493.         return buf
  494.  
  495.     
  496.     def seek(self, pos):
  497.         if pos < self.pos:
  498.             self.init()
  499.         
  500.         self.read(pos - self.pos)
  501.  
  502.     
  503.     def tell(self):
  504.         return self.pos
  505.  
  506.     
  507.     def write(self, data):
  508.         self.pos += len(data)
  509.         raw = self.bz2obj.compress(data)
  510.         self.fileobj.write(raw)
  511.  
  512.     
  513.     def close(self):
  514.         if self.mode == 'w':
  515.             raw = self.bz2obj.flush()
  516.             self.fileobj.write(raw)
  517.         
  518.         self.fileobj.close()
  519.  
  520.  
  521.  
  522. class _FileInFile(object):
  523.     
  524.     def __init__(self, fileobj, offset, size, sparse = None):
  525.         self.fileobj = fileobj
  526.         self.offset = offset
  527.         self.size = size
  528.         self.sparse = sparse
  529.         self.position = 0
  530.  
  531.     
  532.     def tell(self):
  533.         return self.position
  534.  
  535.     
  536.     def seek(self, position):
  537.         self.position = position
  538.  
  539.     
  540.     def read(self, size = None):
  541.         if size is None:
  542.             size = self.size - self.position
  543.         else:
  544.             size = min(size, self.size - self.position)
  545.         if self.sparse is None:
  546.             return self.readnormal(size)
  547.         else:
  548.             return self.readsparse(size)
  549.  
  550.     
  551.     def readnormal(self, size):
  552.         self.fileobj.seek(self.offset + self.position)
  553.         self.position += size
  554.         return self.fileobj.read(size)
  555.  
  556.     
  557.     def readsparse(self, size):
  558.         data = []
  559.         while size > 0:
  560.             buf = self.readsparsesection(size)
  561.             if not buf:
  562.                 break
  563.             
  564.             size -= len(buf)
  565.             data.append(buf)
  566.         return ''.join(data)
  567.  
  568.     
  569.     def readsparsesection(self, size):
  570.         section = self.sparse.find(self.position)
  571.         if section is None:
  572.             return ''
  573.         
  574.         size = min(size, section.offset + section.size - self.position)
  575.  
  576.  
  577.  
  578. class ExFileObject(object):
  579.     blocksize = 1024
  580.     
  581.     def __init__(self, tarfile, tarinfo):
  582.         self.fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data, tarinfo.size, getattr(tarinfo, 'sparse', None))
  583.         self.name = tarinfo.name
  584.         self.mode = 'r'
  585.         self.closed = False
  586.         self.size = tarinfo.size
  587.         self.position = 0
  588.         self.buffer = ''
  589.  
  590.     
  591.     def read(self, size = None):
  592.         if self.closed:
  593.             raise ValueError('I/O operation on closed file')
  594.         
  595.         buf = ''
  596.         if self.buffer:
  597.             if size is None:
  598.                 buf = self.buffer
  599.                 self.buffer = ''
  600.             else:
  601.                 buf = self.buffer[:size]
  602.                 self.buffer = self.buffer[size:]
  603.         
  604.         if size is None:
  605.             buf += self.fileobj.read()
  606.         else:
  607.             buf += self.fileobj.read(size - len(buf))
  608.         self.position += len(buf)
  609.         return buf
  610.  
  611.     
  612.     def readline(self, size = -1):
  613.         if self.closed:
  614.             raise ValueError('I/O operation on closed file')
  615.         
  616.         if '\n' in self.buffer:
  617.             pos = self.buffer.find('\n') + 1
  618.         else:
  619.             buffers = [
  620.                 self.buffer]
  621.             while True:
  622.                 buf = self.fileobj.read(self.blocksize)
  623.                 buffers.append(buf)
  624.                 if not buf or '\n' in buf:
  625.                     self.buffer = ''.join(buffers)
  626.                     pos = self.buffer.find('\n') + 1
  627.                     if pos == 0:
  628.                         pos = len(self.buffer)
  629.                     
  630.                     break
  631.                     continue
  632.         if size != -1:
  633.             pos = min(size, pos)
  634.         
  635.         buf = self.buffer[:pos]
  636.         self.buffer = self.buffer[pos:]
  637.         self.position += len(buf)
  638.         return buf
  639.  
  640.     
  641.     def readlines(self):
  642.         result = []
  643.         while True:
  644.             line = self.readline()
  645.             if not line:
  646.                 break
  647.             
  648.             result.append(line)
  649.         return result
  650.  
  651.     
  652.     def tell(self):
  653.         if self.closed:
  654.             raise ValueError('I/O operation on closed file')
  655.         
  656.         return self.position
  657.  
  658.     
  659.     def seek(self, pos, whence = os.SEEK_SET):
  660.         if self.closed:
  661.             raise ValueError('I/O operation on closed file')
  662.         
  663.         if whence == os.SEEK_SET:
  664.             self.position = min(max(pos, 0), self.size)
  665.         elif whence == os.SEEK_CUR:
  666.             if pos < 0:
  667.                 self.position = max(self.position + pos, 0)
  668.             else:
  669.                 self.position = min(self.position + pos, self.size)
  670.         elif whence == os.SEEK_END:
  671.             self.position = max(min(self.size + pos, self.size), 0)
  672.         else:
  673.             raise ValueError('Invalid argument')
  674.         self.buffer = ''
  675.         self.fileobj.seek(self.position)
  676.  
  677.     
  678.     def close(self):
  679.         self.closed = True
  680.  
  681.     
  682.     def __iter__(self):
  683.         while True:
  684.             line = self.readline()
  685.             if not line:
  686.                 break
  687.             
  688.             yield line
  689.  
  690.  
  691.  
  692. class TarInfo(object):
  693.     
  694.     def __init__(self, name = ''):
  695.         self.name = name
  696.         self.mode = 438
  697.         self.uid = 0
  698.         self.gid = 0
  699.         self.size = 0
  700.         self.mtime = 0
  701.         self.chksum = 0
  702.         self.type = REGTYPE
  703.         self.linkname = ''
  704.         self.uname = 'user'
  705.         self.gname = 'group'
  706.         self.devmajor = 0
  707.         self.devminor = 0
  708.         self.offset = 0
  709.         self.offset_data = 0
  710.  
  711.     
  712.     def __repr__(self):
  713.         return '<%s %r at %#x>' % (self.__class__.__name__, self.name, id(self))
  714.  
  715.     
  716.     def frombuf(cls, buf):
  717.         if len(buf) != BLOCKSIZE:
  718.             raise ValueError('truncated header')
  719.         
  720.         if buf.count(NUL) == BLOCKSIZE:
  721.             raise ValueError('empty header')
  722.         
  723.         tarinfo = cls()
  724.         tarinfo.buf = buf
  725.         tarinfo.name = nts(buf[0:100])
  726.         tarinfo.mode = nti(buf[100:108])
  727.         tarinfo.uid = nti(buf[108:116])
  728.         tarinfo.gid = nti(buf[116:124])
  729.         tarinfo.size = nti(buf[124:136])
  730.         tarinfo.mtime = nti(buf[136:148])
  731.         tarinfo.chksum = nti(buf[148:156])
  732.         tarinfo.type = buf[156:157]
  733.         tarinfo.linkname = nts(buf[157:257])
  734.         tarinfo.uname = nts(buf[265:297])
  735.         tarinfo.gname = nts(buf[297:329])
  736.         tarinfo.devmajor = nti(buf[329:337])
  737.         tarinfo.devminor = nti(buf[337:345])
  738.         prefix = nts(buf[345:500])
  739.         if prefix and not tarinfo.issparse():
  740.             tarinfo.name = prefix + '/' + tarinfo.name
  741.         
  742.         if tarinfo.chksum not in calc_chksums(buf):
  743.             raise ValueError('invalid header')
  744.         
  745.         return tarinfo
  746.  
  747.     frombuf = classmethod(frombuf)
  748.     
  749.     def tobuf(self, posix = False):
  750.         buf = ''
  751.         type = self.type
  752.         prefix = ''
  753.         if self.name.endswith('/'):
  754.             type = DIRTYPE
  755.         
  756.         if type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  757.             name = self.name
  758.         else:
  759.             name = normpath(self.name)
  760.         if type == DIRTYPE:
  761.             name += '/'
  762.         
  763.         linkname = self.linkname
  764.         if linkname:
  765.             linkname = normpath(linkname)
  766.         
  767.         if posix:
  768.             if self.size > MAXSIZE_MEMBER:
  769.                 raise ValueError('file is too large (>= 8 GB)')
  770.             
  771.             if len(self.linkname) > LENGTH_LINK:
  772.                 raise ValueError('linkname is too long (>%d)' % LENGTH_LINK)
  773.             
  774.             if len(name) > LENGTH_NAME:
  775.                 prefix = name[:LENGTH_PREFIX + 1]
  776.                 while prefix and prefix[-1] != '/':
  777.                     prefix = prefix[:-1]
  778.                 name = name[len(prefix):]
  779.                 prefix = prefix[:-1]
  780.                 if not prefix or len(name) > LENGTH_NAME:
  781.                     raise ValueError('name is too long')
  782.                 
  783.             
  784.         elif len(self.linkname) > LENGTH_LINK:
  785.             buf += self._create_gnulong(self.linkname, GNUTYPE_LONGLINK)
  786.         
  787.         if len(name) > LENGTH_NAME:
  788.             buf += self._create_gnulong(name, GNUTYPE_LONGNAME)
  789.         
  790.         parts = [
  791.             stn(name, 100),
  792.             itn(self.mode & 4095, 8, posix),
  793.             itn(self.uid, 8, posix),
  794.             itn(self.gid, 8, posix),
  795.             itn(self.size, 12, posix),
  796.             itn(self.mtime, 12, posix),
  797.             '        ',
  798.             type,
  799.             stn(self.linkname, 100),
  800.             stn(MAGIC, 6),
  801.             stn(VERSION, 2),
  802.             stn(self.uname, 32),
  803.             stn(self.gname, 32),
  804.             itn(self.devmajor, 8, posix),
  805.             itn(self.devminor, 8, posix),
  806.             stn(prefix, 155)]
  807.         buf += ''.join(parts).ljust(BLOCKSIZE, NUL)
  808.         chksum = calc_chksums(buf[-BLOCKSIZE:])[0]
  809.         buf = buf[:-364] + '%06o\x00' % chksum + buf[-357:]
  810.         self.buf = buf
  811.         return buf
  812.  
  813.     
  814.     def _create_gnulong(self, name, type):
  815.         name += NUL
  816.         tarinfo = self.__class__()
  817.         tarinfo.name = '././@LongLink'
  818.         tarinfo.type = type
  819.         tarinfo.mode = 0
  820.         tarinfo.size = len(name)
  821.         buf = tarinfo.tobuf()
  822.         buf += name
  823.         (blocks, remainder) = divmod(len(name), BLOCKSIZE)
  824.         if remainder > 0:
  825.             buf += (BLOCKSIZE - remainder) * NUL
  826.         
  827.         return buf
  828.  
  829.     
  830.     def isreg(self):
  831.         return self.type in REGULAR_TYPES
  832.  
  833.     
  834.     def isfile(self):
  835.         return self.isreg()
  836.  
  837.     
  838.     def isdir(self):
  839.         return self.type == DIRTYPE
  840.  
  841.     
  842.     def issym(self):
  843.         return self.type == SYMTYPE
  844.  
  845.     
  846.     def islnk(self):
  847.         return self.type == LNKTYPE
  848.  
  849.     
  850.     def ischr(self):
  851.         return self.type == CHRTYPE
  852.  
  853.     
  854.     def isblk(self):
  855.         return self.type == BLKTYPE
  856.  
  857.     
  858.     def isfifo(self):
  859.         return self.type == FIFOTYPE
  860.  
  861.     
  862.     def issparse(self):
  863.         return self.type == GNUTYPE_SPARSE
  864.  
  865.     
  866.     def isdev(self):
  867.         return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE)
  868.  
  869.  
  870.  
  871. class TarFile(object):
  872.     debug = 0
  873.     dereference = False
  874.     ignore_zeros = False
  875.     errorlevel = 0
  876.     posix = False
  877.     fileobject = ExFileObject
  878.     
  879.     def __init__(self, name = None, mode = 'r', fileobj = None):
  880.         if len(mode) > 1 or mode not in 'raw':
  881.             raise ValueError("mode must be 'r', 'a' or 'w'")
  882.         
  883.         self._mode = mode
  884.         self.mode = {
  885.             'r': 'rb',
  886.             'a': 'r+b',
  887.             'w': 'wb' }[mode]
  888.         if not fileobj:
  889.             fileobj = file(name, self.mode)
  890.             self._extfileobj = False
  891.         elif name is None and hasattr(fileobj, 'name'):
  892.             name = fileobj.name
  893.         
  894.         if hasattr(fileobj, 'mode'):
  895.             self.mode = fileobj.mode
  896.         
  897.         self._extfileobj = True
  898.         self.name = None if name else None
  899.         self.fileobj = fileobj
  900.         self.closed = False
  901.         self.members = []
  902.         self._loaded = False
  903.         self.offset = self.fileobj.tell()
  904.         self.inodes = { }
  905.         if self._mode == 'r':
  906.             self.firstmember = None
  907.             self.firstmember = self.next()
  908.         
  909.         if self._mode == 'a':
  910.             self.firstmember = None
  911.             while True:
  912.                 
  913.                 try:
  914.                     tarinfo = self.next()
  915.                 except ReadError:
  916.                     self.fileobj.seek(0)
  917.                     break
  918.  
  919.                 if tarinfo is None:
  920.                     self.fileobj.seek(-BLOCKSIZE, 1)
  921.                     break
  922.                     continue
  923.         
  924.         if self._mode in 'aw':
  925.             self._loaded = True
  926.         
  927.  
  928.     
  929.     def open(cls, name = None, mode = 'r', fileobj = None, bufsize = 10240):
  930.         if not name and not fileobj:
  931.             raise ValueError('nothing to open')
  932.         
  933.         if mode in ('r', 'r:*'):
  934.             for comptype in cls.OPEN_METH:
  935.                 func = getattr(cls, cls.OPEN_METH[comptype])
  936.                 if fileobj is not None:
  937.                     saved_pos = fileobj.tell()
  938.                 
  939.                 
  940.                 try:
  941.                     return func(name, 'r', fileobj)
  942.                 continue
  943.                 except (ReadError, CompressionError):
  944.                     if fileobj is not None:
  945.                         fileobj.seek(saved_pos)
  946.                         continue
  947.                     continue
  948.                     continue
  949.                 
  950.  
  951.             
  952.             raise ReadError('file could not be opened successfully')
  953.         elif ':' in mode:
  954.             (filemode, comptype) = mode.split(':', 1)
  955.             if not filemode:
  956.                 pass
  957.             filemode = 'r'
  958.             if not comptype:
  959.                 pass
  960.             comptype = 'tar'
  961.             if comptype in cls.OPEN_METH:
  962.                 func = getattr(cls, cls.OPEN_METH[comptype])
  963.             else:
  964.                 raise CompressionError('unknown compression type %r' % comptype)
  965.             return func(name, filemode, fileobj)
  966.         elif '|' in mode:
  967.             (filemode, comptype) = mode.split('|', 1)
  968.             if not filemode:
  969.                 pass
  970.             filemode = 'r'
  971.             if not comptype:
  972.                 pass
  973.             comptype = 'tar'
  974.             if filemode not in 'rw':
  975.                 raise ValueError("mode must be 'r' or 'w'")
  976.             
  977.             t = cls(name, filemode, _Stream(name, filemode, comptype, fileobj, bufsize))
  978.             t._extfileobj = False
  979.             return t
  980.         elif mode in 'aw':
  981.             return cls.taropen(name, mode, fileobj)
  982.         
  983.         raise ValueError('undiscernible mode')
  984.  
  985.     open = classmethod(open)
  986.     
  987.     def taropen(cls, name, mode = 'r', fileobj = None):
  988.         if len(mode) > 1 or mode not in 'raw':
  989.             raise ValueError("mode must be 'r', 'a' or 'w'")
  990.         
  991.         return cls(name, mode, fileobj)
  992.  
  993.     taropen = classmethod(taropen)
  994.     
  995.     def gzopen(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  996.         if len(mode) > 1 or mode not in 'rw':
  997.             raise ValueError("mode must be 'r' or 'w'")
  998.         
  999.         
  1000.         try:
  1001.             import gzip
  1002.             gzip.GzipFile
  1003.         except (ImportError, AttributeError):
  1004.             raise CompressionError('gzip module is not available')
  1005.  
  1006.         if fileobj is None:
  1007.             fileobj = file(name, mode + 'b')
  1008.         
  1009.         
  1010.         try:
  1011.             t = cls.taropen(name, mode, gzip.GzipFile(name, mode, compresslevel, fileobj))
  1012.         except IOError:
  1013.             raise ReadError('not a gzip file')
  1014.  
  1015.         t._extfileobj = False
  1016.         return t
  1017.  
  1018.     gzopen = classmethod(gzopen)
  1019.     
  1020.     def bz2open(cls, name, mode = 'r', fileobj = None, compresslevel = 9):
  1021.         if len(mode) > 1 or mode not in 'rw':
  1022.             raise ValueError("mode must be 'r' or 'w'.")
  1023.         
  1024.         
  1025.         try:
  1026.             import bz2
  1027.         except ImportError:
  1028.             raise CompressionError('bz2 module is not available')
  1029.  
  1030.         if fileobj is not None:
  1031.             fileobj = _BZ2Proxy(fileobj, mode)
  1032.         else:
  1033.             fileobj = bz2.BZ2File(name, mode, compresslevel = compresslevel)
  1034.         
  1035.         try:
  1036.             t = cls.taropen(name, mode, fileobj)
  1037.         except IOError:
  1038.             raise ReadError('not a bzip2 file')
  1039.  
  1040.         t._extfileobj = False
  1041.         return t
  1042.  
  1043.     bz2open = classmethod(bz2open)
  1044.     OPEN_METH = {
  1045.         'tar': 'taropen',
  1046.         'gz': 'gzopen',
  1047.         'bz2': 'bz2open' }
  1048.     
  1049.     def close(self):
  1050.         if self.closed:
  1051.             return None
  1052.         
  1053.         if self._mode in 'aw':
  1054.             self.fileobj.write(NUL * BLOCKSIZE * 2)
  1055.             self.offset += BLOCKSIZE * 2
  1056.             (blocks, remainder) = divmod(self.offset, RECORDSIZE)
  1057.             if remainder > 0:
  1058.                 self.fileobj.write(NUL * (RECORDSIZE - remainder))
  1059.             
  1060.         
  1061.         if not self._extfileobj:
  1062.             self.fileobj.close()
  1063.         
  1064.         self.closed = True
  1065.  
  1066.     
  1067.     def getmember(self, name):
  1068.         tarinfo = self._getmember(name)
  1069.         if tarinfo is None:
  1070.             raise KeyError('filename %r not found' % name)
  1071.         
  1072.         return tarinfo
  1073.  
  1074.     
  1075.     def getmembers(self):
  1076.         self._check()
  1077.         if not self._loaded:
  1078.             self._load()
  1079.         
  1080.         return self.members
  1081.  
  1082.     
  1083.     def getnames(self):
  1084.         return [ tarinfo.name for tarinfo in self.getmembers() ]
  1085.  
  1086.     
  1087.     def gettarinfo(self, name = None, arcname = None, fileobj = None):
  1088.         self._check('aw')
  1089.         if fileobj is not None:
  1090.             name = fileobj.name
  1091.         
  1092.         if arcname is None:
  1093.             arcname = name
  1094.         
  1095.         arcname = normpath(arcname)
  1096.         (drv, arcname) = os.path.splitdrive(arcname)
  1097.         while arcname[0:1] == '/':
  1098.             arcname = arcname[1:]
  1099.         tarinfo = TarInfo()
  1100.         if fileobj is None:
  1101.             if hasattr(os, 'lstat') and not (self.dereference):
  1102.                 statres = os.lstat(name)
  1103.             else:
  1104.                 statres = os.stat(name)
  1105.         else:
  1106.             statres = os.fstat(fileobj.fileno())
  1107.         linkname = ''
  1108.         stmd = statres.st_mode
  1109.         if stat.S_ISREG(stmd):
  1110.             inode = (statres.st_ino, statres.st_dev)
  1111.             if not (self.dereference) and statres.st_nlink > 1 and inode in self.inodes:
  1112.                 type = LNKTYPE
  1113.                 linkname = self.inodes[inode]
  1114.             else:
  1115.                 type = REGTYPE
  1116.                 if inode[0]:
  1117.                     self.inodes[inode] = arcname
  1118.                 
  1119.         elif stat.S_ISDIR(stmd):
  1120.             type = DIRTYPE
  1121.             if arcname[-1:] != '/':
  1122.                 arcname += '/'
  1123.             
  1124.         elif stat.S_ISFIFO(stmd):
  1125.             type = FIFOTYPE
  1126.         elif stat.S_ISLNK(stmd):
  1127.             type = SYMTYPE
  1128.             linkname = os.readlink(name)
  1129.         elif stat.S_ISCHR(stmd):
  1130.             type = CHRTYPE
  1131.         elif stat.S_ISBLK(stmd):
  1132.             type = BLKTYPE
  1133.         else:
  1134.             return None
  1135.         tarinfo.name = arcname
  1136.         tarinfo.mode = stmd
  1137.         tarinfo.uid = statres.st_uid
  1138.         tarinfo.gid = statres.st_gid
  1139.         if stat.S_ISREG(stmd):
  1140.             tarinfo.size = statres.st_size
  1141.         else:
  1142.             tarinfo.size = 0x0L
  1143.         tarinfo.mtime = statres.st_mtime
  1144.         tarinfo.type = type
  1145.         tarinfo.linkname = linkname
  1146.         if pwd:
  1147.             
  1148.             try:
  1149.                 tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
  1150.             except KeyError:
  1151.                 pass
  1152.             except:
  1153.                 None<EXCEPTION MATCH>KeyError
  1154.             
  1155.  
  1156.         None<EXCEPTION MATCH>KeyError
  1157.         if grp:
  1158.             
  1159.             try:
  1160.                 tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
  1161.             except KeyError:
  1162.                 pass
  1163.             except:
  1164.                 None<EXCEPTION MATCH>KeyError
  1165.             
  1166.  
  1167.         None<EXCEPTION MATCH>KeyError
  1168.         if type in (CHRTYPE, BLKTYPE):
  1169.             if hasattr(os, 'major') and hasattr(os, 'minor'):
  1170.                 tarinfo.devmajor = os.major(statres.st_rdev)
  1171.                 tarinfo.devminor = os.minor(statres.st_rdev)
  1172.             
  1173.         
  1174.         return tarinfo
  1175.  
  1176.     
  1177.     def list(self, verbose = True):
  1178.         self._check()
  1179.         for tarinfo in self:
  1180.             if verbose:
  1181.                 print filemode(tarinfo.mode),
  1182.                 if not tarinfo.uname:
  1183.                     pass
  1184.                 if not tarinfo.gname:
  1185.                     pass
  1186.                 print '%s/%s' % (tarinfo.uid, tarinfo.gid),
  1187.                 if tarinfo.ischr() or tarinfo.isblk():
  1188.                     print '%10s' % '%d,%d' % (tarinfo.devmajor, tarinfo.devminor),
  1189.                 else:
  1190.                     print '%10d' % tarinfo.size,
  1191.                 print '%d-%02d-%02d %02d:%02d:%02d' % time.localtime(tarinfo.mtime)[:6],
  1192.             
  1193.             print tarinfo.name,
  1194.             if verbose:
  1195.                 if tarinfo.issym():
  1196.                     print '->', tarinfo.linkname,
  1197.                 
  1198.                 if tarinfo.islnk():
  1199.                     print 'link to', tarinfo.linkname,
  1200.                 
  1201.             
  1202.             print 
  1203.         
  1204.  
  1205.     
  1206.     def add(self, name, arcname = None, recursive = True):
  1207.         self._check('aw')
  1208.         if arcname is None:
  1209.             arcname = name
  1210.         
  1211.         if self.name is not None and os.path.abspath(name) == self.name:
  1212.             self._dbg(2, 'tarfile: Skipped %r' % name)
  1213.             return None
  1214.         
  1215.         if name == '.':
  1216.             if recursive:
  1217.                 if arcname == '.':
  1218.                     arcname = ''
  1219.                 
  1220.                 for f in os.listdir('.'):
  1221.                     self.add(f, os.path.join(arcname, f))
  1222.                 
  1223.             
  1224.             return None
  1225.         
  1226.         self._dbg(1, name)
  1227.         tarinfo = self.gettarinfo(name, arcname)
  1228.         if tarinfo is None:
  1229.             self._dbg(1, 'tarfile: Unsupported type %r' % name)
  1230.             return None
  1231.         
  1232.         if tarinfo.isreg():
  1233.             f = file(name, 'rb')
  1234.             self.addfile(tarinfo, f)
  1235.             f.close()
  1236.         elif tarinfo.isdir():
  1237.             self.addfile(tarinfo)
  1238.             if recursive:
  1239.                 for f in os.listdir(name):
  1240.                     self.add(os.path.join(name, f), os.path.join(arcname, f))
  1241.                 
  1242.             
  1243.         else:
  1244.             self.addfile(tarinfo)
  1245.  
  1246.     
  1247.     def addfile(self, tarinfo, fileobj = None):
  1248.         self._check('aw')
  1249.         tarinfo = copy.copy(tarinfo)
  1250.         buf = tarinfo.tobuf(self.posix)
  1251.         self.fileobj.write(buf)
  1252.         self.offset += len(buf)
  1253.         if fileobj is not None:
  1254.             copyfileobj(fileobj, self.fileobj, tarinfo.size)
  1255.             (blocks, remainder) = divmod(tarinfo.size, BLOCKSIZE)
  1256.             if remainder > 0:
  1257.                 self.fileobj.write(NUL * (BLOCKSIZE - remainder))
  1258.                 blocks += 1
  1259.             
  1260.             self.offset += blocks * BLOCKSIZE
  1261.         
  1262.         self.members.append(tarinfo)
  1263.  
  1264.     
  1265.     def extractall(self, path = '.', members = None):
  1266.         directories = []
  1267.         if members is None:
  1268.             members = self
  1269.         
  1270.         for tarinfo in members:
  1271.             if tarinfo.isdir():
  1272.                 directories.append(tarinfo)
  1273.                 tarinfo = copy.copy(tarinfo)
  1274.                 tarinfo.mode = 448
  1275.             
  1276.             self.extract(tarinfo, path)
  1277.         
  1278.         directories.sort((lambda a, b: cmp(a.name, b.name)))
  1279.         directories.reverse()
  1280.         for tarinfo in directories:
  1281.             dirpath = os.path.join(path, tarinfo.name)
  1282.             
  1283.             try:
  1284.                 self.chown(tarinfo, dirpath)
  1285.                 self.utime(tarinfo, dirpath)
  1286.                 self.chmod(tarinfo, dirpath)
  1287.             continue
  1288.             except ExtractError:
  1289.                 e = None
  1290.                 if self.errorlevel > 1:
  1291.                     raise 
  1292.                 else:
  1293.                     self._dbg(1, 'tarfile: %s' % e)
  1294.                 self.errorlevel > 1
  1295.             
  1296.  
  1297.         
  1298.  
  1299.     
  1300.     def extract(self, member, path = ''):
  1301.         self._check('r')
  1302.         if isinstance(member, TarInfo):
  1303.             tarinfo = member
  1304.         else:
  1305.             tarinfo = self.getmember(member)
  1306.         if tarinfo.islnk():
  1307.             tarinfo._link_target = os.path.join(path, tarinfo.linkname)
  1308.         
  1309.         
  1310.         try:
  1311.             self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  1312.         except EnvironmentError:
  1313.             e = None
  1314.             if self.errorlevel > 0:
  1315.                 raise 
  1316.             elif e.filename is None:
  1317.                 self._dbg(1, 'tarfile: %s' % e.strerror)
  1318.             else:
  1319.                 self._dbg(1, 'tarfile: %s %r' % (e.strerror, e.filename))
  1320.         except ExtractError:
  1321.             e = None
  1322.             if self.errorlevel > 1:
  1323.                 raise 
  1324.             else:
  1325.                 self._dbg(1, 'tarfile: %s' % e)
  1326.         except:
  1327.             self.errorlevel > 1
  1328.  
  1329.  
  1330.     
  1331.     def extractfile(self, member):
  1332.         self._check('r')
  1333.         if isinstance(member, TarInfo):
  1334.             tarinfo = member
  1335.         else:
  1336.             tarinfo = self.getmember(member)
  1337.         if tarinfo.isreg():
  1338.             return self.fileobject(self, tarinfo)
  1339.         elif tarinfo.type not in SUPPORTED_TYPES:
  1340.             return self.fileobject(self, tarinfo)
  1341.         elif tarinfo.islnk() or tarinfo.issym():
  1342.             if isinstance(self.fileobj, _Stream):
  1343.                 raise StreamError('cannot extract (sym)link as file object')
  1344.             else:
  1345.                 return self.extractfile(self._getmember(tarinfo.linkname, tarinfo))
  1346.         else:
  1347.             return None
  1348.  
  1349.     
  1350.     def _extract_member(self, tarinfo, targetpath):
  1351.         if targetpath[-1:] == '/':
  1352.             targetpath = targetpath[:-1]
  1353.         
  1354.         targetpath = os.path.normpath(targetpath)
  1355.         upperdirs = os.path.dirname(targetpath)
  1356.         if upperdirs and not os.path.exists(upperdirs):
  1357.             os.makedirs(upperdirs)
  1358.         
  1359.         if tarinfo.islnk() or tarinfo.issym():
  1360.             self._dbg(1, '%s -> %s' % (tarinfo.name, tarinfo.linkname))
  1361.         else:
  1362.             self._dbg(1, tarinfo.name)
  1363.         if tarinfo.isreg():
  1364.             self.makefile(tarinfo, targetpath)
  1365.         elif tarinfo.isdir():
  1366.             self.makedir(tarinfo, targetpath)
  1367.         elif tarinfo.isfifo():
  1368.             self.makefifo(tarinfo, targetpath)
  1369.         elif tarinfo.ischr() or tarinfo.isblk():
  1370.             self.makedev(tarinfo, targetpath)
  1371.         elif tarinfo.islnk() or tarinfo.issym():
  1372.             self.makelink(tarinfo, targetpath)
  1373.         elif tarinfo.type not in SUPPORTED_TYPES:
  1374.             self.makeunknown(tarinfo, targetpath)
  1375.         else:
  1376.             self.makefile(tarinfo, targetpath)
  1377.         self.chown(tarinfo, targetpath)
  1378.         if not tarinfo.issym():
  1379.             self.chmod(tarinfo, targetpath)
  1380.             self.utime(tarinfo, targetpath)
  1381.         
  1382.  
  1383.     
  1384.     def makedir(self, tarinfo, targetpath):
  1385.         
  1386.         try:
  1387.             os.mkdir(targetpath, 448)
  1388.         except EnvironmentError:
  1389.             e = None
  1390.             if e.errno != errno.EEXIST:
  1391.                 raise 
  1392.             
  1393.         except:
  1394.             e.errno != errno.EEXIST
  1395.  
  1396.  
  1397.     
  1398.     def makefile(self, tarinfo, targetpath):
  1399.         source = self.extractfile(tarinfo)
  1400.         target = file(targetpath, 'wb')
  1401.         copyfileobj(source, target)
  1402.         source.close()
  1403.         target.close()
  1404.  
  1405.     
  1406.     def makeunknown(self, tarinfo, targetpath):
  1407.         self.makefile(tarinfo, targetpath)
  1408.         self._dbg(1, 'tarfile: Unknown file type %r, extracted as regular file.' % tarinfo.type)
  1409.  
  1410.     
  1411.     def makefifo(self, tarinfo, targetpath):
  1412.         if hasattr(os, 'mkfifo'):
  1413.             os.mkfifo(targetpath)
  1414.         else:
  1415.             raise ExtractError('fifo not supported by system')
  1416.  
  1417.     
  1418.     def makedev(self, tarinfo, targetpath):
  1419.         if not hasattr(os, 'mknod') or not hasattr(os, 'makedev'):
  1420.             raise ExtractError('special devices not supported by system')
  1421.         
  1422.         mode = tarinfo.mode
  1423.         if tarinfo.isblk():
  1424.             mode |= stat.S_IFBLK
  1425.         else:
  1426.             mode |= stat.S_IFCHR
  1427.         os.mknod(targetpath, mode, os.makedev(tarinfo.devmajor, tarinfo.devminor))
  1428.  
  1429.     
  1430.     def makelink(self, tarinfo, targetpath):
  1431.         linkpath = tarinfo.linkname
  1432.         
  1433.         try:
  1434.             if tarinfo.issym():
  1435.                 os.symlink(linkpath, targetpath)
  1436.             else:
  1437.                 os.link(tarinfo._link_target, targetpath)
  1438.         except AttributeError:
  1439.             if tarinfo.issym():
  1440.                 linkpath = os.path.join(os.path.dirname(tarinfo.name), linkpath)
  1441.                 linkpath = normpath(linkpath)
  1442.             
  1443.             
  1444.             try:
  1445.                 self._extract_member(self.getmember(linkpath), targetpath)
  1446.             except (EnvironmentError, KeyError):
  1447.                 e = None
  1448.                 linkpath = os.path.normpath(linkpath)
  1449.                 
  1450.                 try:
  1451.                     shutil.copy2(linkpath, targetpath)
  1452.                 except EnvironmentError:
  1453.                     e = None
  1454.                     raise IOError('link could not be created')
  1455.                 except:
  1456.                     None<EXCEPTION MATCH>EnvironmentError
  1457.                 
  1458.  
  1459.                 None<EXCEPTION MATCH>EnvironmentError
  1460.             
  1461.  
  1462.             None<EXCEPTION MATCH>(EnvironmentError, KeyError)
  1463.  
  1464.  
  1465.     
  1466.     def chown(self, tarinfo, targetpath):
  1467.         if pwd and hasattr(os, 'geteuid') and os.geteuid() == 0:
  1468.             
  1469.             try:
  1470.                 g = grp.getgrnam(tarinfo.gname)[2]
  1471.             except KeyError:
  1472.                 
  1473.                 try:
  1474.                     g = grp.getgrgid(tarinfo.gid)[2]
  1475.                 except KeyError:
  1476.                     g = os.getgid()
  1477.                 except:
  1478.                     None<EXCEPTION MATCH>KeyError
  1479.                 
  1480.  
  1481.                 None<EXCEPTION MATCH>KeyError
  1482.  
  1483.             
  1484.             try:
  1485.                 u = pwd.getpwnam(tarinfo.uname)[2]
  1486.             except KeyError:
  1487.                 
  1488.                 try:
  1489.                     u = pwd.getpwuid(tarinfo.uid)[2]
  1490.                 except KeyError:
  1491.                     u = os.getuid()
  1492.                 except:
  1493.                     None<EXCEPTION MATCH>KeyError
  1494.                 
  1495.  
  1496.                 None<EXCEPTION MATCH>KeyError
  1497.  
  1498.             
  1499.             try:
  1500.                 if tarinfo.issym() and hasattr(os, 'lchown'):
  1501.                     os.lchown(targetpath, u, g)
  1502.                 elif sys.platform != 'os2emx':
  1503.                     os.chown(targetpath, u, g)
  1504.             except EnvironmentError:
  1505.                 e = None
  1506.                 raise ExtractError('could not change owner')
  1507.             except:
  1508.                 None<EXCEPTION MATCH>EnvironmentError
  1509.             
  1510.  
  1511.         None<EXCEPTION MATCH>EnvironmentError
  1512.  
  1513.     
  1514.     def chmod(self, tarinfo, targetpath):
  1515.         if hasattr(os, 'chmod'):
  1516.             
  1517.             try:
  1518.                 os.chmod(targetpath, tarinfo.mode)
  1519.             except EnvironmentError:
  1520.                 e = None
  1521.                 raise ExtractError('could not change mode')
  1522.             except:
  1523.                 None<EXCEPTION MATCH>EnvironmentError
  1524.             
  1525.  
  1526.         None<EXCEPTION MATCH>EnvironmentError
  1527.  
  1528.     
  1529.     def utime(self, tarinfo, targetpath):
  1530.         if not hasattr(os, 'utime'):
  1531.             return None
  1532.         
  1533.         if sys.platform == 'win32' and tarinfo.isdir():
  1534.             return None
  1535.         
  1536.         
  1537.         try:
  1538.             os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
  1539.         except EnvironmentError:
  1540.             e = None
  1541.             raise ExtractError('could not change modification time')
  1542.  
  1543.  
  1544.     
  1545.     def next(self):
  1546.         self._check('ra')
  1547.         if self.firstmember is not None:
  1548.             m = self.firstmember
  1549.             self.firstmember = None
  1550.             return m
  1551.         
  1552.         self.fileobj.seek(self.offset)
  1553.         while True:
  1554.             buf = self.fileobj.read(BLOCKSIZE)
  1555.             if not buf:
  1556.                 return None
  1557.             
  1558.             
  1559.             try:
  1560.                 tarinfo = TarInfo.frombuf(buf)
  1561.                 tarinfo.offset = self.offset
  1562.                 self.offset += BLOCKSIZE
  1563.                 tarinfo = self.proc_member(tarinfo)
  1564.             except ValueError:
  1565.                 e = None
  1566.                 if self.ignore_zeros:
  1567.                     self._dbg(2, '0x%X: empty or invalid block: %s' % (self.offset, e))
  1568.                     self.offset += BLOCKSIZE
  1569.                     continue
  1570.                 elif self.offset == 0:
  1571.                     raise ReadError('empty, unreadable or compressed file: %s' % e)
  1572.                 
  1573.                 return None
  1574.  
  1575.             break
  1576.         if tarinfo.isreg() and tarinfo.name.endswith('/'):
  1577.             tarinfo.type = DIRTYPE
  1578.         
  1579.         if tarinfo.isdir() and not tarinfo.name.endswith('/'):
  1580.             tarinfo.name += '/'
  1581.         
  1582.         self.members.append(tarinfo)
  1583.         return tarinfo
  1584.  
  1585.     
  1586.     def proc_member(self, tarinfo):
  1587.         if tarinfo.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK):
  1588.             return self.proc_gnulong(tarinfo)
  1589.         elif tarinfo.type == GNUTYPE_SPARSE:
  1590.             return self.proc_sparse(tarinfo)
  1591.         else:
  1592.             return self.proc_builtin(tarinfo)
  1593.  
  1594.     
  1595.     def proc_builtin(self, tarinfo):
  1596.         tarinfo.offset_data = self.offset
  1597.         if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES:
  1598.             self.offset += self._block(tarinfo.size)
  1599.         
  1600.         return tarinfo
  1601.  
  1602.     
  1603.     def proc_gnulong(self, tarinfo):
  1604.         buf = ''
  1605.         count = tarinfo.size
  1606.         while count > 0:
  1607.             block = self.fileobj.read(BLOCKSIZE)
  1608.             buf += block
  1609.             self.offset += BLOCKSIZE
  1610.             count -= BLOCKSIZE
  1611.             continue
  1612.             self
  1613.         b = self.fileobj.read(BLOCKSIZE)
  1614.         t = TarInfo.frombuf(b)
  1615.         t.offset = self.offset
  1616.         self.offset += BLOCKSIZE
  1617.         next = self.proc_member(t)
  1618.         next.offset = tarinfo.offset
  1619.         if tarinfo.type == GNUTYPE_LONGNAME:
  1620.             next.name = nts(buf)
  1621.         elif tarinfo.type == GNUTYPE_LONGLINK:
  1622.             next.linkname = nts(buf)
  1623.         
  1624.         return next
  1625.  
  1626.     
  1627.     def proc_sparse(self, tarinfo):
  1628.         buf = tarinfo.buf
  1629.         sp = _ringbuffer()
  1630.         pos = 386
  1631.         lastpos = 0x0L
  1632.         realpos = 0x0L
  1633.         for i in xrange(4):
  1634.             
  1635.             try:
  1636.                 offset = nti(buf[pos:pos + 12])
  1637.                 numbytes = nti(buf[pos + 12:pos + 24])
  1638.             except ValueError:
  1639.                 break
  1640.  
  1641.             if offset > lastpos:
  1642.                 sp.append(_hole(lastpos, offset - lastpos))
  1643.             
  1644.             sp.append(_data(offset, numbytes, realpos))
  1645.             realpos += numbytes
  1646.             lastpos = offset + numbytes
  1647.             pos += 24
  1648.         
  1649.         isextended = ord(buf[482])
  1650.         origsize = nti(buf[483:495])
  1651.         while isextended == 1:
  1652.             buf = self.fileobj.read(BLOCKSIZE)
  1653.             self.offset += BLOCKSIZE
  1654.             pos = 0
  1655.             for i in xrange(21):
  1656.                 
  1657.                 try:
  1658.                     offset = nti(buf[pos:pos + 12])
  1659.                     numbytes = nti(buf[pos + 12:pos + 24])
  1660.                 except ValueError:
  1661.                     self
  1662.                     self
  1663.                     break
  1664.                 except:
  1665.                     self
  1666.  
  1667.                 if offset > lastpos:
  1668.                     sp.append(_hole(lastpos, offset - lastpos))
  1669.                 
  1670.                 sp.append(_data(offset, numbytes, realpos))
  1671.                 realpos += numbytes
  1672.                 lastpos = offset + numbytes
  1673.                 pos += 24
  1674.             
  1675.             isextended = ord(buf[504])
  1676.         if lastpos < origsize:
  1677.             sp.append(_hole(lastpos, origsize - lastpos))
  1678.         
  1679.         tarinfo.sparse = sp
  1680.         tarinfo.offset_data = self.offset
  1681.         self.offset += self._block(tarinfo.size)
  1682.         tarinfo.size = origsize
  1683.         return tarinfo
  1684.  
  1685.     
  1686.     def _block(self, count):
  1687.         (blocks, remainder) = divmod(count, BLOCKSIZE)
  1688.         if remainder:
  1689.             blocks += 1
  1690.         
  1691.         return blocks * BLOCKSIZE
  1692.  
  1693.     
  1694.     def _getmember(self, name, tarinfo = None):
  1695.         members = self.getmembers()
  1696.         if tarinfo is None:
  1697.             end = len(members)
  1698.         else:
  1699.             end = members.index(tarinfo)
  1700.         for i in xrange(end - 1, -1, -1):
  1701.             if name == members[i].name:
  1702.                 return members[i]
  1703.                 continue
  1704.         
  1705.  
  1706.     
  1707.     def _load(self):
  1708.         while True:
  1709.             tarinfo = self.next()
  1710.             if tarinfo is None:
  1711.                 break
  1712.                 continue
  1713.         self._loaded = True
  1714.  
  1715.     
  1716.     def _check(self, mode = None):
  1717.         if self.closed:
  1718.             raise IOError('%s is closed' % self.__class__.__name__)
  1719.         
  1720.         if mode is not None and self._mode not in mode:
  1721.             raise IOError('bad operation for mode %r' % self._mode)
  1722.         
  1723.  
  1724.     
  1725.     def __iter__(self):
  1726.         if self._loaded:
  1727.             return iter(self.members)
  1728.         else:
  1729.             return TarIter(self)
  1730.  
  1731.     
  1732.     def _dbg(self, level, msg):
  1733.         if level <= self.debug:
  1734.             print >>sys.stderr, msg
  1735.         
  1736.  
  1737.  
  1738.  
  1739. class TarIter:
  1740.     
  1741.     def __init__(self, tarfile):
  1742.         self.tarfile = tarfile
  1743.         self.index = 0
  1744.  
  1745.     
  1746.     def __iter__(self):
  1747.         return self
  1748.  
  1749.     
  1750.     def next(self):
  1751.         if not self.tarfile._loaded:
  1752.             tarinfo = self.tarfile.next()
  1753.             if not tarinfo:
  1754.                 self.tarfile._loaded = True
  1755.                 raise StopIteration
  1756.             
  1757.         else:
  1758.             
  1759.             try:
  1760.                 tarinfo = self.tarfile.members[self.index]
  1761.             except IndexError:
  1762.                 raise StopIteration
  1763.  
  1764.         self.index += 1
  1765.         return tarinfo
  1766.  
  1767.  
  1768.  
  1769. class _section:
  1770.     
  1771.     def __init__(self, offset, size):
  1772.         self.offset = offset
  1773.         self.size = size
  1774.  
  1775.     
  1776.     def __contains__(self, offset):
  1777.         return None if offset <= offset else offset < self.offset + self.size
  1778.  
  1779.  
  1780.  
  1781. class _data(_section):
  1782.     
  1783.     def __init__(self, offset, size, realpos):
  1784.         _section.__init__(self, offset, size)
  1785.         self.realpos = realpos
  1786.  
  1787.  
  1788.  
  1789. class _hole(_section):
  1790.     pass
  1791.  
  1792.  
  1793. class _ringbuffer(list):
  1794.     
  1795.     def __init__(self):
  1796.         self.idx = 0
  1797.  
  1798.     
  1799.     def find(self, offset):
  1800.         idx = self.idx
  1801.         while True:
  1802.             item = self[idx]
  1803.             if offset in item:
  1804.                 break
  1805.             
  1806.             idx += 1
  1807.             if idx == len(self):
  1808.                 idx = 0
  1809.             
  1810.             if idx == self.idx:
  1811.                 return None
  1812.                 continue
  1813.         self.idx = idx
  1814.         return item
  1815.  
  1816.  
  1817. TAR_PLAIN = 0
  1818. TAR_GZIPPED = 8
  1819.  
  1820. class TarFileCompat:
  1821.     
  1822.     def __init__(self, file, mode = 'r', compression = TAR_PLAIN):
  1823.         if compression == TAR_PLAIN:
  1824.             self.tarfile = TarFile.taropen(file, mode)
  1825.         elif compression == TAR_GZIPPED:
  1826.             self.tarfile = TarFile.gzopen(file, mode)
  1827.         else:
  1828.             raise ValueError('unknown compression constant')
  1829.         if mode[0:1] == 'r':
  1830.             members = self.tarfile.getmembers()
  1831.             for m in members:
  1832.                 m.filename = m.name
  1833.                 m.file_size = m.size
  1834.                 m.date_time = time.gmtime(m.mtime)[:6]
  1835.             
  1836.         
  1837.  
  1838.     
  1839.     def namelist(self):
  1840.         return map((lambda m: m.name), self.infolist())
  1841.  
  1842.     
  1843.     def infolist(self):
  1844.         return filter((lambda m: m.type in REGULAR_TYPES), self.tarfile.getmembers())
  1845.  
  1846.     
  1847.     def printdir(self):
  1848.         self.tarfile.list()
  1849.  
  1850.     
  1851.     def testzip(self):
  1852.         pass
  1853.  
  1854.     
  1855.     def getinfo(self, name):
  1856.         return self.tarfile.getmember(name)
  1857.  
  1858.     
  1859.     def read(self, name):
  1860.         return self.tarfile.extractfile(self.tarfile.getmember(name)).read()
  1861.  
  1862.     
  1863.     def write(self, filename, arcname = None, compress_type = None):
  1864.         self.tarfile.add(filename, arcname)
  1865.  
  1866.     
  1867.     def writestr(self, zinfo, bytes):
  1868.         
  1869.         try:
  1870.             StringIO = StringIO
  1871.             import cStringIO
  1872.         except ImportError:
  1873.             StringIO = StringIO
  1874.             import StringIO
  1875.  
  1876.         import calendar
  1877.         zinfo.name = zinfo.filename
  1878.         zinfo.size = zinfo.file_size
  1879.         zinfo.mtime = calendar.timegm(zinfo.date_time)
  1880.         self.tarfile.addfile(zinfo, StringIO(bytes))
  1881.  
  1882.     
  1883.     def close(self):
  1884.         self.tarfile.close()
  1885.  
  1886.  
  1887.  
  1888. def is_tarfile(name):
  1889.     
  1890.     try:
  1891.         t = open(name)
  1892.         t.close()
  1893.         return True
  1894.     except TarError:
  1895.         return False
  1896.  
  1897.  
  1898. open = TarFile.open
  1899.